<?php
namespace App\Core;

use App\Repositories\InterfaceRepository;
use App\Traits\ReturnTrait;
use Hyperf\DbConnection\Db;
class Node
{
    use ReturnTrait;

    public function view(InterfaceRepository $repository,$top,$line)
    {
        $results = $repository->model()::query()->orderBy('lft', 'asc')->get()->toArray();
        $parent = array();
        $arr_list = [];
        if($top){
            $arr_list[0]['id']=0;
            $arr_list[0]['name'] = '顶级分类';
            $arr_list[0]['depth'] = 0;
        }
        foreach ($results as $item) {
            if (count($parent)) {
                while (count($parent) - 1 > 0 && $parent[count($parent) - 1]['rgt'] < $item['rgt']) {
                    array_pop($parent);
                }
            }
            $parent[] = $item;
            $arr_list[] = $item;
        }
        //显示树状结构
        if($line){
            foreach ($arr_list as $key=>$list) {
                $arr_list[$key]['name']=str_repeat('└', $list['depth']) . $list['name'];
            }
        }
        return $arr_list;
    }

    public function tree($data,$pid = 0, $field_id="id", $parent_field="parent_id") {
        $arr = array();
        foreach ($data as $k=>$v) {
            if ($v->$parent_field == $pid) {
                $arr[$k] = $v->toArray();
                $arr[$k]['children'] = $this->tree($data,  $v->$field_id, $field_id, $parent_field);
            }
        }
        return $arr;
    }

    public function store(InterfaceRepository $repository,$model,$is_user_id=false)
    {
        $parent_id = $model->parent_id;
        if(isset($model->id)&&$model->id)
        {
//            if(!$model->save()){
//               return $this->error('保存失败');
//            })

            $old_parent_id = $model->getOriginal('parent_id');
            if($old_parent_id==$model->parent_id){
                if(!$model->save()){
                    return $this->error('保存失败');
                }
                return $this->success($model);
            }else{
                if(!$model->save()){
                    return $this->error('保存失败');
                }
                $original_lft = $model->lft;
                $original_rgt = $model->rgt;
                $update_num = $original_rgt-$original_lft;//要修改的 节点数   修改元素个数为修改节点数/2
                $temp = $original_lft-1;
                $move_ids = $repository->model()::query()->where('lft','>=',$original_lft)
                    ->where('rgt','<=',$original_rgt)->get()->pluck('id')->toArray();
                $repository->model()::query()->where('lft','>=',$original_lft)
                    ->where('rgt','<=',$original_rgt)->update([
                        'lft' => DB::raw('0-(lft-'.$temp.')'),
                        'rgt' => DB::raw('0-(rgt-'.$temp.')'),
                    ]);//将修改的元素的节点数重新排序  并置为负数，防止影响到其它节点
                $repository->model()::query()->where('lft','>',$original_lft)->update(['lft'=>DB::raw("lft-($original_rgt-$original_lft+1)")]);
                $repository->model()::query()->where('rgt','>',$original_rgt)->update(['rgt'=>DB::raw("rgt-($original_rgt-$original_lft+1)")]);
                if(!$is_user_id){
                    $parent = $repository->getById($model->parent_id);
                }else{
                    $parent = $repository->one('*',[[
                        'field' => 'user_id',
                        'value' => $model->parent_id
                    ]]);
                }
                $target_lft = $parent?$parent->lft:0;
                $target_rgt = $parent?$parent->rgt:0;
                $target_depth = $parent?$parent->depth:0;
                $current_category_target_depth = $target_depth?$target_depth+1:0;
                $calc_depth = $model->depth-$current_category_target_depth;
                $count = 0;
                if($parent){
                    $count = $repository->model()::query()->where('lft','>',$parent->lft)
                        ->where('rgt','<',$parent->rgt)->count('id');
                }
                if($count){
                    $result = $repository->model()::query()->select('rgt')->where('lft','>',$target_lft)->where('rgt','<',$target_rgt)
                        ->orderBY('rgt','desc')->first();
                    $new_rgt = $result->rgt;
                    $repository->model()::query()->where('lft','>',$new_rgt)->update(['lft'=>DB::raw("lft+$update_num+1")]);
                    $repository->model()::query()->where('rgt','>',$new_rgt)->update(['rgt'=>DB::raw("rgt+$update_num+1")]);
                    $repository->model()::query()->whereIn('id',$move_ids)->update([
                        'lft' => DB::raw("0-lft+$new_rgt"),
                        'rgt'=>DB::raw("0-rgt+$new_rgt"),
                        'depth' => DB::raw("depth-$calc_depth")
                    ]);
//                    $repository->model()::query()->where('lft','>',$target_lft)->update(['lft'=>DB::raw("lft+$update_num+1")]);
//                    $repository->model()::query()->where('rgt','>',$target_lft)->update(['rgt'=>DB::raw("rgt+$update_num+1")]);
//                    $repository->model()::query()->whereIn('id',$move_ids)->update([
//                        'lft' => DB::raw("0-lft+$new_rgt"),
//                        'rgt'=>DB::raw("0-rgt+$new_rgt")
//                    ]);
                }else{
                    $repository->model()::query()->where('lft','>',$target_lft)->update(['lft'=>DB::raw("lft+($original_rgt-$original_lft+1)")]);
                    $repository->model()::query()->where('rgt','>=',$target_rgt)->update(['rgt'=>DB::raw("rgt+($original_rgt-$original_lft+1)")]);
                    $repository->model()::query()->whereIn('id',$move_ids)->update([
                        'lft' => DB::raw("0-lft+$target_lft"),
                        'rgt' => DB::raw("0-rgt+$target_lft"),
                        'depth' => DB::raw("depth-$calc_depth")
                    ]);
                }
                return $this->success($model);
            }
        }else{
            if($parent_id){
                if(!$is_user_id){
                    $parent = $repository->model()::query()->find($parent_id);
                }else{
                    $parent = $repository->model()::query()->where('user_id',$parent_id)->first();
                }
                $model->lft = $parent->lft+1;
                $model->rgt = $parent->lft+2;
                DB::beginTransaction();
                try{
                    $update_lft_count = $repository->model()::query()->where('lft','>',$parent->lft)->count('id');
                    if($update_lft_count && !$repository->model()::query()->where('lft','>',$parent->lft)->update(['lft'=>DB::raw('lft+2')])){
                        throw new \Exception('更新左树失败');
                    }
                    $update_rgt_count = $repository->model()::query()->where('rgt','>',$parent->lft)->count('id');
                    if($update_rgt_count&&!$repository->model()::query()->where('rgt','>',$parent->lft)->update(['rgt'=>DB::raw('rgt+2')])){
                        throw new \Exception('更新右树失败');
                    }
                    $model->lft = $parent->lft+1;
                    $model->rgt = $parent->lft+2;
                    $model->depth = $parent->depth+1;
                    if(!$model->save()){
                        throw new \Exception('创建失败');
                    }
                    DB::commit();
                }catch (\Throwable $exception){
                    DB::rollBack();
                    return $this->error($exception->getMessage());
                }
                return $this->success($model);
            }else{
                $max_category = $repository->model()::query()->where('parent_id',0)->orderBy('rgt','desc')->first();
                $model->lft = $max_category?$max_category->rgt+1:1;
                $model->rgt = $max_category?$max_category->rgt+2:2;
                $model->depth = 0;
                if($model->save())
                {
                    return $this->success($model);
                }
                return $this->error('保存失败');
            }
        }
    }

    public function delete(InterfaceRepository $repository,$model)
    {
        $lft = $model->lft;
        $rgt = $model->rgt;
        //计算$width
        $width = $rgt-$lft + 1;
        $model->delete();
        $repository->model()::query()->where('lft','>',$lft)->where('rgt','<',$rgt)->delete();//删除子分类
        $repository->model()::query()->where('lft','>',$lft)->update([
            'lft' => DB::raw("lft-$width")
        ]);
        $repository->model()::query()->where('rgt','>',$rgt)->update([
            'rgt' => DB::raw("rgt-$width")
        ]);
        return $this->success();
    }
}
